Skip to content

fixed issue #1080, re-enable failing udp tests on windows #1167

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Nov 30, 2019

Conversation

dtacalau
Copy link
Contributor

@dtacalau dtacalau commented Nov 25, 2019

Fixes issues #1080 & #1131.

Couple of fixes two re-enable two udp tests which were failing on windows.
Added two new tests to check ET for UDP sockets, tests rely on a WouldBlock recv(_from) to reregister the socket and reset the interests.
Added a note in the read/peek(_from) docs that on Windows reading with a too small a buffer will return an error.

No need to emulate edge-triggers for UDP sockets by doing reregister on partial reads/write.

@dtacalau dtacalau marked this pull request as ready for review November 25, 2019 16:34
@dtacalau
Copy link
Contributor Author

@Thomasdezeeuw please review, thanks!

}

pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
try_io!(self, recv_from, buf)
try_io!(self.recv_from(buf), |t: &(usize, SocketAddr)| match t {
(bytes_read, _) => *bytes_read <= buf.len(),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UDP doesn't work the same way TCP does. Calling recv(_from) will receive a single packet. Because of thisbuf is usually 1 << 16 bytes (~65k, the maximum size of a single packet) and most read packets will be smaller then that. Which means that it will always re-register, which emulating level triggers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case we need to always reregister for recv(_from) on successfull op.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reverted this change, not needed.

@dtacalau dtacalau force-pushed the issue_1080 branch 3 times, most recently from adbbb4b to ceb9bd5 Compare November 25, 2019 20:42
}

pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
try_io!(self, peek, buf)
}

pub fn connect(&self, addr: SocketAddr) -> io::Result<()> {
self.inner.connect(addr)
let result = self.inner.connect(addr);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure this is required?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't think its required, see comment in udp_socket_edge_triggered_behavior test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you're right, not required.

expect_read!(socket1.recv(&mut buf[..max]), &DATA2[..max]);
}
if cfg!(target_os = "windows") {
// On Windows, read all data, reading part of data returns error WSAEMSGSIZE (10040)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not split up this test in Windows/others. Lets just read the entire packet on all platform.

Also lets add a note in the read/peek(_from) docs that on Windows reading with a too small a buffer will return an error. Encouraging people to use 1 << 16 sized buffers (the maximum size for a UDP packet).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, will read all

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added note for all read/peek(_from)

@@ -387,7 +391,15 @@ fn unconnected_udp_socket_connected_methods() {
);

// Socket is unconnected, but we're using an connected method.
assert_error(socket1.send(DATA1), "address required");
if cfg!(not(target_os = "windows")) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here as above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if possible, there are different error messages on Windows vs other platforms. How would you have one assert checking two different expected messages?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think mio makes any guarantees as to error messages. It doesn't matter terribly to me if the test only check that an error is received or it adds cfg flags to test messages per platform.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can just change this to assert_error(socket1.send(DATA1), "address") and add a comment saying it must say something about missing an address. Then we don't have this complex cfg! stuff.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather not change this, unless you have a strong reason against it. Having cfg! in tests doesn't feel complex at all, actually it's weird we don't have more cfg! in them. Having just an assert_error(socket1.send(DATA1), "address") doesn't say much about the actual error you are expecting there. "address required" is enough to get an idea, "no address was supplied. (os error 10057)" is even better. IMO tests should be as explicit as possible.

}

pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
try_io!(self, peek, buf)
}

pub fn connect(&self, addr: SocketAddr) -> io::Result<()> {
self.inner.connect(addr)
let result = self.inner.connect(addr);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't think its required, see comment in udp_socket_edge_triggered_behavior test.

@dtacalau
Copy link
Contributor Author

@Thomasdezeeuw I found some interesting things related to ET while playing with tests. This PR depends on the conclusion from here #1131 (comment)

Signed-off-by: Daniel Tacalau <[email protected]>
@dtacalau dtacalau changed the title reregister on partial reads/write for UDP sockets fixed issue #1080, re-enable failing udp tests on windows Nov 27, 2019
@dtacalau
Copy link
Contributor Author

@carllerche please review, thanks!

@dtacalau
Copy link
Contributor Author

#1174 opened to investigate *nix behavior.

Copy link
Member

@carllerche carllerche left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

…ndows. One tests needed to have interests reregistered by calling a blocking recv. Another tests needed a Windows specific assert error message.

Signed-off-by: Daniel Tacalau <[email protected]>
… is larger than the buffer specified, the buffer is filled with the first part of the data, and peek returns the error WSAEMSGSIZE(10040). The excess data is lost. Make sure to always use a sufficiently large buffer to hold the maximum UDP packet size, which can be up to 64 kilobytes in size.

Signed-off-by: Daniel Tacalau <[email protected]>
…se tests rely on having a blocking recv(_from) reregistering the socket and reseting the interests.

Signed-off-by: Daniel Tacalau <[email protected]>
Copy link
Collaborator

@Thomasdezeeuw Thomasdezeeuw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some small nits, but looks good overall.

src/net/udp.rs Outdated
/// is filled with the first part of the data, and recv_from returns the error
/// WSAEMSGSIZE(10040). The excess data is lost.
/// Make sure to always use a sufficiently large buffer to hold the
/// maximum UDP packet size, which can be up to 64 kilobytes in size.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its actually 65536 bytes, lets just use 1 << 16.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for the other notes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

64 kilobytes is 65536 bytes. I will replace with 65536 bytes, which is the most explicit, I dont find 1 << 16 better.

@@ -387,7 +391,15 @@ fn unconnected_udp_socket_connected_methods() {
);

// Socket is unconnected, but we're using an connected method.
assert_error(socket1.send(DATA1), "address required");
if cfg!(not(target_os = "windows")) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can just change this to assert_error(socket1.send(DATA1), "address") and add a comment saying it must say something about missing an address. Then we don't have this complex cfg! stuff.

socket1.connect(address2).unwrap();

let mut buf = [0; 20];
checked_write!(socket1.send(DATA1));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Writing without receiving an writable event first.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, will expect writable before

vec![ExpectEvent::new(ID2, Interests::WRITABLE)],
);

{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't think this extra block is needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, removed

@dtacalau
Copy link
Contributor Author

Some small nits, but looks good overall.

@Thomasdezeeuw fixed some of them.

@Thomasdezeeuw Thomasdezeeuw merged commit 8603167 into tokio-rs:master Nov 30, 2019
dtacalau added a commit to dtacalau/mio that referenced this pull request Dec 4, 2019
…kio-rs#1167)

* fixed assert arguments order

Signed-off-by: Daniel Tacalau <[email protected]>

* fix issue tokio-rs#1080, re-enabled and fixed UDP tests failing on Windows. One tests needed to have interests reregistered by calling a blocking recv. Another tests needed a Windows specific assert error message.

Signed-off-by: Daniel Tacalau <[email protected]>

* Added a note in the read/peek(_from) docs that on Windows if the data is larger than the buffer specified, the buffer is filled with the first part of the data, and peek returns the error WSAEMSGSIZE(10040). The excess data is lost. Make sure to always use a sufficiently large buffer to hold the maximum UDP packet size, which can be up to 64 kilobytes in size.

Signed-off-by: Daniel Tacalau <[email protected]>

* Added two new tests verifying ET behavior for UDP sockets events. These tests rely on having a blocking recv(_from) reregistering the socket and reseting the interests.

Signed-off-by: Daniel Tacalau <[email protected]>

* replaces 64 kilobytes with 65536 bytes in the notes

Signed-off-by: Daniel Tacalau <[email protected]>

* changes after review for new et tests: removed unneeded block, expect a writable before actual write

Signed-off-by: Daniel Tacalau <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants